home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- *
- * Apple Developer Technical Support
- *
- * AppleEvent specific routines
- *
- * Program: AEObject-Edition Sample
- * File: AppleEventCore.c - C Source
- *
- * by: C.K. Haun <TR>
- *
- * Copyright © 1990-1992 Apple Computer, Inc.
- * All rights reserved.
- *
- *------------------------------------------------------------------------------
- * This file handles the generic AppleEvent handlers, as well as intialization
- * and installing the handlers I'll need for this application.
- * Also installs my coercion handlers and has the interaction Idle proc.
- * Other, more specific AE handling (like edition functions) are in the functional
- * area files.
- * Functions that deal specifically with AppleEvent™ Objects are in the
- * file AEObject.c.
- *----------------------------------------------------------------------------*/
- /* AESample v1: Removed all ShowMe error notifications, replaced with macro to display */
- /* errors non-intrusively in AESatus window */
-
- #define __AEM__
-
- #pragma segment Main
- /* DoHighLevel will be in main, just because */
- #include "Sampdefines.h"
-
-
-
- /* DoHighLevel processes our high level events */
- /* All the HLEs that come into my application get dispatched to here. */
- /* All I do is call AEProcessAppleEvent, because I do not support any */
- /* other types of High Level Events, justs AEs. */
- void DoHighLevel(EventRecord AERecord)
- {
- OSErr fred2;
- /* Process the event. */
- /* Here's what happens;
- 1) If this is an AppleEvent, and we have a handler installed for this event,
- AEProcessAppleEvent jumps to that handler
- else
- 2) If there is a system handler for this event, AEProcessAppleEvent jumps to that
- else
- 3) return errEventNotHandled.
- */
- /* •••• NOTE: If you are sending AppleEvents to yourself (using a PSN of kCurrentProcess */
- /* in the address AEDesc to AECreateAppleEvent) then events sent to yourself that */
- /* way will NOT come here! They will be dispatched directly to the */
- /* correct handler by the AppleEvent manager! Try it in this sample. */
- fred2 = AEProcessAppleEvent(&AERecord);
- if ((fred2 != userCanceledErr) && (fred2 != noErr) && (fred2 != errAEEventNotHandled))
- mAEErrorDisplay("\pAppleEvent Proccessing.", fred2)
- /* if it was a userCanceledErr (from the quit routine) and the reply has been */
- /* sent from there already */
- /* if it's a errAEEventNotHandled, then someone sent us an event we're not prepared for, */
- /* that is not a reason to put up a dialog. Since anyone can send us events, then */
- /* we could get all kinds of stray stuff, so just ignore it. */
- /* you may want to check for debugging reasons */
- }
-
- /* end DoHighLevel */
-
- #pragma segment AppleEvents
- /***************************************************************************************
-
- MissedAnyParameters
-
- Used to check for any unread required parameters. Returns true if we missed at
- least one.
-
- *****************************************************************************************/
- Boolean MissedAnyParameters(AppleEvent *message)
- {
- OSErr err;
- DescType ignoredActualType;
- AEKeyword missedKeyword;
- Size ignoredActualSize;
- EventRecord event;
-
- err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeKeyword, &ignoredActualType, (Ptr)&missedKeyword,
- sizeof(missedKeyword), &ignoredActualSize);
-
- /* no error means that we found some more.*/
-
- if (!err) {
- event.message = *(long *)&ignoredActualType;
- event.where = *(Point *)&missedKeyword;
- mAEErrorDisplay("\pMissedAnyParameters: got parameters I don't know what to do with.", err)
- err = errAEEventNotHandled;
- }
-
- /* errAEDescNotFound means that there are no more parameters. If we get */
- /* an error code other than that, flag it. */
-
- else if (err != errAEDescNotFound) {
- mAEErrorDisplay("\pMissedAnyParameters: after AEGetAttributeDesc.", err)
-
- }
- return(err != errAEDescNotFound);
- }
-
- /* This is the standard Open Application event. You'll get this as one of the (if not the ) */
- /* first events in your application. So, we open up a blank document */
- /* You will _NOT_ get this if you were launched with an event (like an 'odoc' or 'pdoc' ) */
- /* so do _not_ do application initialiaztion things here! This routine may never */
- /* get called! */
- pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- OSErr myErr = noErr;
- #pragma unused (messagein,refIn)
- gCurrentReply = reply;
-
- ChangePlane(AddNewWindow(true)); /* open our initial, blank window */
- /* and make sure it's the front window */
-
- mAEErrorDisplay("\pOpen App Handler", myErr)
- gCurrentReply = nil;
- return(myErr);
- }
-
- /* end AEOpenHandler */
-
- /* Open Doc, opens our documents. Remember, this can happen at application start AND */
- /* anytime else. If your app is up and running and the user goes to the desktop, hilites one */
- /* of your files, and double-clicks or selects Open from the finder File menu this event */
- /* handler will get called. Which means you don't do any initialization of globals here, or */
- /* anything else except open then doc. */
- /* SO -- Do NOT assume that you are at app start time in this */
- /* routine, or bad things will surely happen to you. */
-
- pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- OSErr myErr = noErr;
- #pragma unused ( refIn)
- gCurrentReply = reply;
-
- /* In previous versions I was coming to the front on this message. This is _not_ */
- /* the proper thing to do. I have changed things to call AEInteractWithUser. */
- /* The user (or the AEm will bring us forward if appropriate). But we may _not_ be */
- /*required to come forward, it may be perfectly reasonable to stay in the background */
- /* so don't do anything unless you really need to, like to put up a dialog */
- /* which we don't have to, so just press on */
- myErr = processOpenPrint(messagein, false);
- gCurrentReply = nil;
- return(myErr);
- }
-
- /* Same logic as OpenDoc */
- pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- { /* no printing handler in yet, so we'll ignore this */
- /* the operation is functionally identical to the ODOC event, with the additon */
- /* of calling your print routine. */
- #pragma unused (refIn)
- gCurrentReply = reply;
- processOpenPrint(messagein, true);
- gCurrentReply = nil;
- return(noErr);
- }
-
- /* Standard Quit event handler, to handle a Quit event from the Finder, for example. */
- /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life. */
- /* OK, it's a few months after I wrote that comment, and I've seen a lot of code */
- /* come through DTS that calls ExitToShell from quit handlers. Let me explain... */
- /* When an AppleEvent Handler is called (like this quit handler) you are ALMOST */
- /* 100% in your application world. A5 is right, you can call any toolbox function, */
- /* you can call your own routines, everything _seems_ like you are in complete */
- /* control. Well, almost but not quite. The routine has been dispatch to from the */
- /* AppleEvent Manager's space, so you _must_ return to that at some point! */
- /* Which is why you can't call ETS from here. When you call ExitToShell from an */
- /* AE Handler, the most likely thing that happens is the FInder quits, and your */
- /* application keeps running. Which ain't what you want, y'know? */
- /* so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!! */
- pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (messagein,refIn)
- OSErr theErr;
- Str32 userCanx;
- gCurrentReply = reply;
- theErr = PrepQuit(); /* prepQuit sets the Stop flag for us. It does _NOT_ quit, you */
- /* should NEVER quit from an AppleEvent handler. Calling */
- /* ExitToShell here would blow things up */
-
- if (!theErr){
- gCurrentReply = nil;
- return(noErr);}
- if (theErr == (userCanceledErr)) {
- /* reply to the application that told us to quit */
- GetIndString(userCanx,kGeneralStrings,kUCanxString);
- AEPutParamPtr(reply, keyErrorNumber, typeLongInteger, (Ptr)&theErr, sizeof(OSErr));
- AEPutParamPtr(reply, keyErrorString, typeChar, (Ptr)&userCanx, userCanx[0]);
- }
- gCurrentReply = nil;
- return(theErr);
-
- }
-
- /* This is the 'ansr', or answer, handler. You need this if you ever want to */
- /* use QueueReply as an option to AESend (which you will) since the reply */
- /* is going to be coming in through your event loop like any other */
- /* AppleEvent. So here it is */
- pascal OSErr AEAnswerHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (refIn)
- OSErr myErr = noErr;
- gCurrentReply = reply;
- mVerboseOutput("\p\nGot an answer from an event")
- DisplayReturnedData((AEDesc *)messagein);
- gCurrentReply = nil;
- return(myErr);
- /* •••• NOTE: One thing you may want to consider, and it's a side-effect of */
- /* the AppleEvent manager's direct dispatching of events if you send them to yourself */
- /* using the kCurrentProcess Process Serial Number constant. */
- /* If you use kCurrentProcess, then the AppleEvent manager will directly dispatch */
- /* to the AppleEvent handler, the event will _not_ go through WaitNextEvent. */
- /* Normally, that's a very good thing. But there is one potential problem.... */
- /* It means that kQueueReply doesn't quite work the way you think it will when sending to */
- /* yourself. The reply will _not_ be put in the event queue, instead this Answer hander */
- /* will be called directly. And if you reply from the answer handler, that will dispatch right */
- /* back to itself. And so on. So be aware that Queued replies are _not_ really */
- /* queued when you are using kCurrentProcess! */
- }
-
-
- /* my routine to snatch a section handle out of an AppleEvent */
- OSErr GetSectionHandleFromEvent(AppleEvent *AEin, SectionHandle *theSection)
- {
- DescType thisType;
- Size returnedSize;
- return(AEGetParamPtr(AEin, keyDirectObject, typeSectionH, &thisType, (Ptr)theSection, sizeof(theSection), &returnedSize));
- }
-
- /* processOpenPrint handles ODOC and PDOC events. Both events open a document, one prints it */
- OSErr processOpenPrint(AppleEvent *messagein, Boolean printIt)
- {
- OSErr err;
- OSErr err2;
- AEDesc theDesc;
- FSSpec theFSS;
- register qq;
- long numFilesToOpen;
- AEKeyword ignoredKeyWord;
- DescType ignoredType;
- Size ignoredSize;
- WindowPtr tWind;
- err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &theDesc);
- if (err) {
- mAEErrorDisplay("\pGetParamDesc error in Open/Print", err)
- }
- if (!MissedAnyParameters(messagein)) {
-
- /* Got all the parameters we need. Now, go through the direct object, */
- /* see what type it is, and parse it up. */
-
- if (err = AECountItems(&theDesc, &numFilesToOpen)) {
- mAEErrorDisplay("\pAECountItems error in Open/Print", err)
- } else {
- for (qq = 1; ((qq <= numFilesToOpen) && (!err)); ++qq) {
- if (err = AEGetNthPtr(&theDesc, qq, typeFSS, &ignoredKeyWord, &ignoredType, (Ptr)&theFSS, sizeof(theFSS),
- &ignoredSize)) {
- mAEErrorDisplay("\pAEGetNthPtr in Open/Print", err)
-
- } else {
- FInfo fileInfo;
- FSpGetFInfo(&theFSS, &fileInfo); /* make sure it's a data file */
- if (fileInfo.fdCreator == kMySignature && fileInfo.fdType == kMyDocumentFileType)
- tWind = OpenFile(&theFSS);
- else
- tWind = nil; /* they may have double clicked on the prefs file */
- }
- if (printIt && tWind != nil) {
-
- PrintIt(tWind, false); /* in Print.c. Does not yet print, but the idea is there */
- CloseMyWindow(tWind);
- }
- } /* for qq = ... */
- } /* AECountItems OK */
- } /* Got all necessary parameters */
-
- if (err2 = AEDisposeDesc(&theDesc)) {
- mAEErrorDisplay("\pAEDisposeDesc in Open/Print", err2)
- }
- return(err ? err : err2);
- }
-
- /* This is an AppleEvent Idle function. It can be passed to AEInteractWithUser */
- /* or AESend. */
- /* What it does is this; */
- /* If some AppleEvent thing is taking a really long time, the AppleEvent manager */
- /* will call WaitNextEvent FOR you (yeah, yeah, only one event loop per app, oh well) */
- /* and give you a result (limited) if you need to do something. That something */
- /* will only be an update,activate,OSevent, or null event */
- pascal Boolean CommonIdleFunction(EventRecord *whatEvent, long *sleeping, RgnHandle *mouseRgn)
- {
- extern Boolean gInBackground;
-
- extern RgnHandle mousergn;
- switch (whatEvent->what) {
- case updateEvt:
- DrawIt((WindowPtr)whatEvent->message); /* draw whatever window needs an update */
-
- break;
- case activateEvt:
- if (whatEvent->modifiers & activeFlag)
- DrawIt((WindowPtr)whatEvent->message);
- break;
- case app4Evt: /* or kOSEvent, I'm old fashioned */
- switch ((whatEvent->message >> 24) & 0x0FF) { /* high byte of message */
- case suspendResumeMessage: /* suspend/resume is also an activate/deactivate */
- gInBackground = (whatEvent->message & kResumeMask) == 0;
- if (gInBackground) {
- SpitClip(); /* export the clipboard please */
- /* deactivate the current TextEdit record as necessary */
- if (FrontWindow() != nil) {
- windowCHandle tempCH = (windowCHandle)GetWRefCon(FrontWindow());
- if ((*tempCH)->boxHandle != nil)
- TEDeactivate((*tempCH)->boxHandle);
- }
- } else {
- if (FrontWindow() != nil) {
- windowCHandle tempCH = (windowCHandle)GetWRefCon(FrontWindow());
- if ((*tempCH)->boxHandle != nil)
- TEActivate((*tempCH)->boxHandle);
- }
- }
- break;
- }
- break;
- case nullEvent:
- AdjustCursor(whatEvent->where, mousergn);
- *sleeping = 20; /* may as well sleep a while */
- *mouseRgn = mousergn;
- break;
-
- }
- return(false); /* If it takes for-ever I will wait, for you... Sorry. */
- }
-
- AEIdleUPP gCommonIdleFunctionUPP = NewAEIdleProc(CommonIdleFunction);
-
- /* This function sends a GetData AppleEvent to someone, and displays the */
- /* results in the AEStatus window */
- void SendGetData(short which)
- {
- AEDesc thisAddress;
- AppleEvent theEvent;
- AEDesc reply;
- OSErr myErr = noErr;
- /* first make an address */
- MakeAddress(&thisAddress);
- myErr = AECreateAppleEvent(kAECoreSuite, kAEGetData, &thisAddress, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
- myErr = BuildGetDataEvent(&theEvent, which); /* in AEObjects.c */
- if (!myErr) {
- /* reply may or may not be used, depending on the reply mode you have set */
- myErr = DoSend(&theEvent, &reply);
- if (!myErr) {
- /* display the results, if we were in WaitReply */
- if (gReplyMode == 1)
- DisplayReturnedData(&reply);
- }
- }
- }
- /* This function sends a SetData AppleEvent to someone, and displays the */
- /* results in the AEStatus window */
- void SendSetData(short which)
- {
- AEDesc thisAddress;
- AppleEvent theEvent;
- AEDesc reply;
- OSErr myErr = noErr;
- /* first make an address */
- MakeAddress(&thisAddress);
- myErr = AECreateAppleEvent(kAECoreSuite, kAESetData, &thisAddress, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
- myErr = BuildSetDataEvent(&theEvent, which); /* in AEObjects.c */
- if (!myErr) {
- DoSend(&theEvent, &reply);
- }
- }
-
-
- /* Dialog box handler for the Interaction Settings you want to use for this sample */
- void SetInteractionLevels(void)
- {
- /* call my common start routine and preset some buttons */
- DialogPtr tdial = CommonDStart(kInteractionDialog, gLocalInteraction + 6, gAESendInteraction + 9);
- short hitItem = 0;
- /* save some stuff in case the user cancels */
- short saveMode1 = gLocalInteraction;
- short saveMode2 = gAESendInteraction;
- short saveMode3 = gAESwitchLayer;
-
- /* one additial item to set */
- SetControlValue(SnatchHandle(tdial, kSwitchLItem), gAESwitchLayer);
-
- /* run the dialog */
- {
- ModalFilterUPP upp = NewModalFilterProc(standardDialogFilter);
-
- while (hitItem != ok && hitItem != cancel) {
- ModalDialog(upp, &hitItem);
- switch (hitItem) {
- case kSelfIItem:
- case kLocalIItem:
- case kAllIItem:
- /* check boxes, just toggle them */
- SetControlValue(SnatchHandle(tdial, gLocalInteraction + kSelfIItem), false);
- gLocalInteraction = hitItem - kSelfIItem;
- SetControlValue(SnatchHandle(tdial, gLocalInteraction + kSelfIItem), true);
- break;
-
- case kNeverIItem:
- case kCanIItem:
- case kAlwaysIItem:
- /* more toggleable checkboxes */
- SetControlValue(SnatchHandle(tdial, gAESendInteraction + kNeverIItem), false);
- gAESendInteraction = hitItem - kNeverIItem;
- SetControlValue(SnatchHandle(tdial, gAESendInteraction + kNeverIItem), true);
-
- break;
- case kSwitchLItem:
- gAESwitchLayer = (gAESwitchLayer ? false : kAECanSwitchLayer);
- SetControlValue(SnatchHandle(tdial, kSwitchLItem), gAESwitchLayer);
- break;
- default:
- break;
- }
- }
- DisposeDialog(tdial);
- DisposeRoutineDescriptor(upp);
- }
-
- if (hitItem == cancel) {
- /* if they canceled, restore the old values */
- gLocalInteraction = saveMode1;
- gAESendInteraction = saveMode2;
- gAESwitchLayer = saveMode3;
-
- } else {
- /* set interaction levels to what the user picked */
- AESetInteractionAllowed(gLocalInteraction);
- }
- }
-
- /* Dialog box handler for the addressing mode you want to use for this sample */
- void SetTargetAddress(void)
- {
- /* bring up dialog and preset some stuff */
- DialogPtr tdial = CommonDStart(kAddressingDialog, gAddressMode + kSelfAddressCurrItem, 0);
- short hitItem = 0;
- short saveMode = gAddressMode;
- /* if an address is already specified, draw it in the box */
- ParamText(&targetName, "", "", "");
- /* dim out the 'Select Target' button if the right check box is not set */
- if (gAddressMode + kSelfAddressCurrItem != kOtherAppItem)
- HiliteControl(SnatchHandle(tdial, kSelectProcItem), 255); /* can't find the constant for dimmed, somebody tell me where it is,please */
-
- {
- ModalFilterUPP upp = NewModalFilterProc(standardDialogFilter);
- /* run the dialog */
- while (hitItem != ok && hitItem != cancel) {
- ModalDialog(upp, &hitItem);
- switch (hitItem) {
- case kSelfAddressCurrItem:
- case kSelfAddressPSNItem:
- case kOtherAppItem:
- /* checkbox toggling, and also setting the hilite state of the 'Set Target' */
- /* button as necessary */
- SetControlValue(SnatchHandle(tdial, gAddressMode + kSelfAddressCurrItem), false);
- gAddressMode = hitItem - kSelfAddressCurrItem;
- SetControlValue(SnatchHandle(tdial, gAddressMode + kSelfAddressCurrItem), true);
- if (gAddressMode + kSelfAddressCurrItem != kOtherAppItem)
- HiliteControl(SnatchHandle(tdial, kSelectProcItem), 255);
- else
- HiliteControl(SnatchHandle(tdial, kSelectProcItem), 0);
- break;
- case kSelectProcItem:
- /* Call the PPC browser to select a target */
- BrowseForTarget(&gTargetAddress);
- break;
- default:
- break;
- }
- }
- DisposeRoutineDescriptor(upp);
- }
- DisposeDialog(tdial);
- /* restore old mode if they canceled */
- if (hitItem == cancel)
- gAddressMode = saveMode;
-
- }
-
- /* Dialog box handler for the Reply Settings you want to use for this sample */
- void SetReplyMode(void)
- {
- DialogPtr tdial = CommonDStart(kReplyModeDialog, gReplyMode + kNoReplyItem, 0);
- short hitItem = 0;
- short saveMode = gReplyMode;
-
- /* set up to gray out the 'no reply' button */
- HiliteControl(SnatchHandle(tdial, kNoReplyItem), 255);
-
- {
- ModalFilterUPP upp = NewModalFilterProc(standardDialogFilter);
- while (hitItem != ok && hitItem != cancel) {
- ModalDialog(upp, &hitItem);
- switch (hitItem) {
- case kNoReplyItem:
- case kWaitReplyItem:
- case kQueueReplyItem:
- SetControlValue(SnatchHandle(tdial, gReplyMode + kNoReplyItem), false);
- gReplyMode = hitItem - kNoReplyItem;
- SetControlValue(SnatchHandle(tdial, gReplyMode + kNoReplyItem), true);
- break;
- default:
- break;
- }
- }
- DisposeRoutineDescriptor(upp);
- }
-
- DisposeDialog(tdial);
- if (hitItem == cancel)
- gReplyMode = saveMode;
- }
-
-
- /* CoerceBooleanToChar creates a desc that says True or False. It's not a very */
- /* interesting coercion, but it's a nice sample. I use it for my output window */
- pascal OSErr CoerceBooleanToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result)
- {
- #pragma unused (refCon)
- OSErr myErr = noErr;
- /* make sure everything is fine first */
- if (origData != typeBoolean || toType != typeChar) {
- /* something is goofy here */
- myErr = errAECoercionFail;
- } else {
- /* a boolean should be two bytes. if it isn't, I'm confused */
- if (theSize == sizeof(short)) {
- short theBool = *((short *)inPtr);
- short index;
- Str32 theText;
- index = theBool ? kTrueWord : kFalseWord;
- GetIndString(theText, kGeneralStrings, index);
- myErr = AECreateDesc(typeChar, (Ptr)&theText[1], theText[0], result);
- } else {
- myErr = errAECoercionFail;
- }
- }
- return(myErr);
- }
-
- /* CoerceQDRectToChar is the same kinda thing */
- pascal OSErr CoerceQDRectToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result)
- {
- #pragma unused (theSize,refCon)
- OSErr myErr = noErr;
- /* make sure everything is fine first */
- if (origData != typeQDRectangle || toType != typeChar) {
- myErr = errAECoercionFail;
- } else {
- short *myRect = (short *)inPtr;
- register qq;
- Str255 theString;
- Str32 tempString;
- Str32 spaceString = "\p ";
-
- theString[0] = 0;
- GetIndString(theString, kGeneralStrings, kSayRectangle);
- for (qq = 0; qq < kFour; qq++) {
- NumToString(*myRect, tempString);
- AppendString(theString, tempString);
- AppendString(theString, spaceString);
- myRect = myRect + 1; /* I have had trouble with MPW C doing a += on a pointer, so I'll do it this way */
- }
- myErr = AECreateDesc(typeChar, (Ptr)&theString[1], theString[0], result);
- }
- return(myErr);
- }
-
- /* these next two I really do find useful, dealing with Toolbox strings */
- pascal OSErr CoerceCharToPString(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result)
- {
- #pragma unused (origData,toType,refCon)
- OSErr myErr = noErr;
- Str255 theString;
- theString[0] = theSize;
- BlockMove(inPtr, (Ptr)&theString[1], theSize);
- myErr = AECreateDesc(typeMyPString, (Ptr)&theString[0], theString[0] + 1, result);
-
- return(myErr);
- }
-
- pascal OSErr CoercePStringToChar(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *result)
- {
- #pragma unused (origData,toType,refCon)
- OSErr myErr = noErr;
- myErr = AECreateDesc(typeChar, (Ptr)(inPtr + 1), theSize - 1, result);
-
-
- return(myErr);
- }
-
- /* CoerceAliasToTargetID takes an applicaiton alias and coerces it to a process target ID */
- /* Of course, to do this is needs to find and launch the application */
- /* This handler uses pointers to the data, since the AppleEvent managr can handle this type */
- /* of manipulation more efficiently than passing descs. You can install a desc handler */
- /* instead, if you'd like. */
- /* I actually don't use this in this sample, but I left it in as an example */
- /* of a coercion handler */
- pascal OSErr CoerceAliasToTargetID(DescType origData, Ptr inPtr, Size theSize, DescType toType, long refCon, AEDesc *returnID)
- {
- #pragma unused (origData,toType,refCon)
- OSErr myErr;
- LaunchParamBlockRec launchThis;
- FSSpec theSpec;
- Boolean changed;
- Handle theAlias = NewHandle(theSize);
- HLock(theAlias);
- BlockMove(inPtr, (Ptr)*theAlias, theSize);
- HUnlock(theAlias);
- launchThis.launchAppSpec = &theSpec;
- /* the caller may have already done this, but it doesn't hurt to do it again */
- myErr = ResolveAlias(nil, (AliasHandle)theAlias, launchThis.launchAppSpec, &changed);
- if (myErr)
- return(myErr);
- /* launch the thing */
- launchThis.launchBlockID = extendedBlock;
- launchThis.launchEPBLength = extendedBlockLen;
- launchThis.launchFileFlags = nil;
- /* launchdontswitch because we just want to use the service. Also, it may be a */
- /* background only application, so like you don't want it to come up, y'know? */
- launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchDontSwitch;
- launchThis.launchAppParameters = nil;
- myErr = LaunchApplication(&launchThis);
- if (myErr) {
- mAEErrorDisplay("\pLaunchApplication error", myErr)
- return(myErr);
- }
- /* it launched. the PSN has been stored in the launchProcessSN field, now we have to make */
- /* that a target */
- /* fill in all the details for the target */
- /* we'll just use the PSN to communicate */
- myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&launchThis.launchProcessSN, sizeof(ProcessSerialNumber), returnID);
- mAEErrorDisplay("\pCreateDesc error after launch", myErr)
- return(myErr);
- }
-
-
- #undef __AEM__
-